﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
using CommunityToolkit.Mvvm.ComponentModel;

namespace Tvnc;

public class Vnc
{
    /// <summary>
    /// 连接信息数组
    /// </summary>
    public VncItemCollection Items { get; set; } = [];
}

public class VncItemCollection : ObservableCollection<VncItem>
{
}

public partial class VncItem : INotifyPropertyChanged
{
    private bool _fitwindow = true;

    /// <summary>
    /// 地址
    /// </summary>
    public string Host { get; set; }

    /// <summary>
    /// 说明
    /// </summary>
    public string Description { get; set; }

    /// <summary>
    /// 密码
    /// </summary>
    public string Password { get; set; }

    /// <summary>
    /// 是否全屏
    /// </summary>
    public bool Fullscreen { get; set; }

    /// <summary>
    /// 缩放Auto
    /// </summary>
    public bool Fitwindow
    {
        get => _fitwindow;
        set
        {
            if (value == _fitwindow) return;
            _fitwindow = value;
            OnPropertyChanged();
        }
    }

    /// <summary>
    /// 缩放比例
    /// </summary>
    public double Scale { get; set; } = 100;


    internal string _password
    {
        get => AesEncryption.DecryptString(Password);
        set => Password = AesEncryption.EncryptString(value);
    }

    public event PropertyChangedEventHandler? PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    protected bool SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
    {
        if (EqualityComparer<T>.Default.Equals(field, value)) return false;
        field = value;
        OnPropertyChanged(propertyName);
        return true;
    }
}

[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(VncItem))]
[JsonSerializable(typeof(VncItemCollection))]
[JsonSerializable(typeof(Vnc))]
internal partial class SourceGenerationContext : JsonSerializerContext
{
}

internal class AesEncryption
{
    private static readonly string key = "oP9wZ6vG6zC2eK3kI3nM3bR9oF9uU0sM"; // 32字节密钥
    private static readonly string iv = "xS9jK1hM8lB4uZ3g"; // 16字节IV

    /// <summary>
    /// 加密字符串
    /// </summary>
    /// <param name="plainText"></param>
    /// <returns></returns>
    public static string EncryptString(string plainText)
    {
        try
        {
            using var aesAlg = Aes.Create();
            aesAlg.Key = Encoding.UTF8.GetBytes(key); // 32字节密钥
            aesAlg.IV = Encoding.UTF8.GetBytes(iv); // 16字节初始向量
            ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
            using var msEncrypt = new MemoryStream();
            using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
            using (var swEncrypt = new StreamWriter(csEncrypt))
            {
                swEncrypt.Write(plainText);
            }

            return Convert.ToBase64String(msEncrypt.ToArray());
        }
        catch
        {
            return "";
        }
    }

    /// <summary>
    /// 解密字符串
    /// </summary>
    /// <param name="cipherText"></param>
    /// <returns></returns>
    public static string DecryptString(string cipherText)
    {
        try
        {
            using var aesAlg = Aes.Create();
            aesAlg.Key = Encoding.UTF8.GetBytes(key); // 32字节密钥
            aesAlg.IV = Encoding.UTF8.GetBytes(iv); // 16字节初始向量
            ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
            using var msDecrypt = new MemoryStream(Convert.FromBase64String(cipherText));
            using var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
            using var srDecrypt = new StreamReader(csDecrypt);
            return srDecrypt.ReadToEnd();
        }
        catch
        {
            return "";
        }
    }
}